﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using FluentValidation;
using FluentValidation.Attributes;

namespace Rhino_Mocks.Models {
    [Validator(typeof(UserInfoValidator))]
    public class UserInfoModel : BaseNopModel {
        public string UserName { get; set; }
        [NoTrim]
        public string Password { get; set; }
    }
    [ModelBinder(typeof(NopModelBinder))]
    public partial class BaseNopModel {
        //public Dictionary<string, object> CustomProperties { get; set; }
        //public BaseNopModel()
        //{
        //    this.CustomProperties = new Dictionary<string, object>();
        //    this.PostInitialize();
        //}
        //public virtual void BindModel(ControllerContext controllerContext, ModelBindingContext bingdingContext)
        //{ }
        //protected void PostInitialize()
        //{ }
    }

    public class NopModelBinder : DefaultModelBinder {
        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var model = base.BindModel(controllerContext, bindingContext);
            //if (model is BaseNopModel)
            //{
            //    ((BaseNopModel)model).BindModel(controllerContext, bindingContext);
            //}
            return model;
        }
        /// <summary>
        /// 过滤实体字段内容包含空格
        /// </summary>
        /// <param name="controllerContext"></param>
        /// <param name="bindingContext"></param>
        /// <param name="propertyDescriptor"></param>
        /// <param name="value"></param>
        protected override void SetProperty(ControllerContext controllerContext, ModelBindingContext bindingContext, PropertyDescriptor propertyDescriptor, object value)
        {
            if (propertyDescriptor.PropertyType == typeof(string))
            {
                if (propertyDescriptor.Attributes.Cast<object>().All(a => a.GetType() != typeof(NoTrimAttribute)))
                {
                    var stringValue = (string)value;
                    value = string.IsNullOrEmpty(stringValue) ? stringValue : stringValue.Trim();
                }
            }
            base.SetProperty(controllerContext, bindingContext, propertyDescriptor, value);
        }
    }
    /// <summary>
    /// 标识是否要过滤字符串包含空格字符
    /// </summary>
    public class NoTrimAttribute : Attribute { }

    public class UserInfoValidator : BaseValidator<UserInfoModel> {
        public UserInfoValidator()
        {
            RuleFor(x => x.UserName).Length(8, 10).WithMessage("username's length less than 8 to 10.");
            RuleFor(x => x.Password).NotEmpty().WithMessage("password is not empty.");
        }
    }

    public abstract class BaseValidator<T> : AbstractValidator<T> where T : class {

    }

    public class ModelValidatorFactory : AttributedValidatorFactory {
        public override IValidator GetValidator(Type type)
        {
            if (type != null)
            {
                var attribute = (ValidatorAttribute)Attribute.GetCustomAttribute(type, typeof(ValidatorAttribute));
                if ((attribute != null) && (attribute.ValidatorType != null))
                {
                    var instance = Activator.CreateInstance(attribute.ValidatorType);
                    return instance as IValidator;
                }
            }
            return null;
        }
    }
}